home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue50 / HTML / mleTagResolvers.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-08  |  7.7 KB  |  329 lines

  1. unit mleTagResolvers;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes, DBTables, dpoBase, usXMLDoc;
  7.  
  8. type
  9.   TControlType = (ctUnknown, ctEditBox, ctCheckBox, ctSelect, ctTable);
  10.  
  11. const
  12.   CONTROL_TYPE_NAMES: array[TControlType] of string =
  13.     ('', 'edit', 'checkbox', 'select', 'table');
  14.  
  15. type
  16.   TTagResolver = class;
  17.   TTagResolverClass = class of TTagResolver;
  18.  
  19.   TTagResolver = class
  20.   private
  21.     FParent: TTagResolver;
  22.     FTagElement: TusXMLElement;
  23.   protected
  24.     HTML: TStringList;
  25.  
  26.     { Functional methods }
  27.     procedure GetAttributes; virtual;
  28.     procedure GetSubtags;
  29.     procedure HandleSubtag(aElement: TusXMLElement; var aHandled: Boolean); virtual;
  30.  
  31.     { Helper methods }
  32.     function GetAttribute(aName, aDefault: string): string;
  33.   public
  34.     constructor Create(aParent: TTagResolver; aTagElement: TusXMLElement);
  35.     destructor Destroy; override;
  36.     function GetHTML: string; virtual;
  37.     procedure Resolve; virtual;
  38.     procedure Setup; virtual;
  39.   end;
  40.  
  41.   TSimpleControlTagResolver = class(TTagResolver)
  42.   protected
  43.     AType: string;
  44.     AName: string;
  45.     AValue: string;
  46.     procedure GetAttributes; override;
  47.   public
  48.     procedure Resolve; override;
  49.   end;
  50.  
  51.   TSMLTagResolver = class(TTagResolver)
  52.   protected
  53.     procedure HandleSubtag(aElement: TusXMLElement; var aHandled: Boolean); override;
  54.   end;
  55.  
  56.   TDataObjectTagResolver = class(TTagResolver)
  57.   protected
  58.     AClassName: string;
  59.     AName: string;
  60.     AOID: string;
  61.     AClass: TDataObjectClass;
  62.     procedure GetAttributes; override;
  63.   public
  64.     procedure Resolve; override;
  65.   end;
  66.  
  67.   TControlTagResolver = class(TTagResolver)
  68.   protected
  69.     AType: string;
  70.     AName: string;
  71.     APropertyName: string;
  72.     AValue: string;
  73.     XType: TControlType;
  74.     procedure GetAttributes; override;
  75.     function GetPropertyValue(aPropertyReference: string): string;
  76.   public
  77.     procedure Resolve; override;
  78.   end;
  79.  
  80.   TObjectCache = class(TStringList)
  81.   public
  82.     constructor Create;
  83.     destructor Destroy; override;
  84.     procedure Clear; override;
  85.     function GetPropertyValue(aPropertyName: string): string;
  86.   end;
  87.  
  88. var
  89.   MLEDatabase: TDatabase;
  90.   ObjectCache: TObjectCache;
  91.  
  92. implementation
  93.  
  94. uses
  95.   SysUtils;
  96.  
  97. { TObjectCache }
  98.  
  99. procedure TObjectCache.Clear;
  100. var
  101.   I: Integer;
  102. begin
  103.   for I := 0 to Count - 1 do
  104.     TDataObject(Objects[I]).Free;
  105.   inherited Clear;
  106. end;
  107.  
  108. constructor TObjectCache.Create;
  109. begin
  110.   inherited;
  111.   Sorted := True;
  112.   Duplicates := dupError;
  113. end;
  114.  
  115. destructor TObjectCache.Destroy;
  116. begin
  117.   Clear;
  118.   inherited;
  119. end;
  120.  
  121. function TObjectCache.GetPropertyValue(aPropertyName: string): string;
  122. var
  123.   ObjectName: string;
  124.   PropertyName: string;
  125.   I: Integer;
  126. begin
  127.   I := Pos('.', aPropertyName);
  128.   ObjectName := Copy(aPropertyName, 1, I - 1);
  129.   PropertyName := Copy(aPropertyName, I + 1, Length(aPropertyName) - I);
  130.   I := IndexOf(ObjectName);
  131.   if I = -1 then
  132.     raise Exception.CreateFmt('Invalid object name: "%s"', [ObjectName]);
  133.   Result := TDataObject(Objects[I]).PropertyByName(PropertyName).AsString;
  134. end;
  135.  
  136. { TTagResolver }
  137.  
  138. constructor TTagResolver.Create(aParent: TTagResolver; aTagElement: TusXMLElement);
  139. begin
  140.   inherited Create;
  141.   FParent := aParent;
  142.   FTagElement := aTagElement;
  143.   HTML := TStringList.Create;
  144. end;
  145.  
  146. destructor TTagResolver.Destroy;
  147. begin
  148.   HTML.Free;
  149.   inherited;
  150. end;
  151.  
  152. function TTagResolver.GetAttribute(aName, aDefault: string): string;
  153. var
  154.   Attr: TusXMLAttribute;
  155. begin
  156.   Result := aDefault;
  157.   Attr := FTagElement.Attributes.GetByName(aName);
  158.   if Assigned(Attr) then
  159.     Result := Attr.Value;
  160. end;
  161.  
  162. procedure TTagResolver.GetAttributes;
  163. begin
  164.   // do nothing; not all tags will have attributes
  165. end;
  166.  
  167. function TTagResolver.GetHTML: string;
  168. begin
  169.   Result := '';
  170.   if HTML.Count <> 0 then
  171.     Result := HTML.Text;
  172. end;
  173.  
  174. procedure TTagResolver.GetSubtags;
  175. var
  176.   I: Integer;
  177.   Handled: Boolean;
  178. begin
  179.   for I := 0 to FTagElement.Subtags.Count - 1 do
  180.   begin
  181.     Handled := False;
  182.     HandleSubtag(FTagElement.Subtags[I], Handled);
  183.     if not Handled then
  184.       raise Exception.CreateFmt('Unexpected subtag <%s>', [FTagElement.Subtags[I].TagName]);
  185.   end;
  186. end;
  187.  
  188. procedure TTagResolver.HandleSubtag(aElement: TusXMLElement;
  189.   var aHandled: Boolean);
  190. begin
  191.   // Do nothing; not all tags will have subtags
  192. end;
  193.  
  194. procedure TTagResolver.Resolve;
  195. begin
  196.   // Do nothing; logic is tag-specific
  197. end;
  198.  
  199. procedure TTagResolver.Setup;
  200. begin
  201.   GetAttributes;
  202.   GetSubtags;
  203. end;
  204.  
  205. { TSMLTagResolver }
  206.  
  207. procedure TSMLTagResolver.HandleSubtag(aElement: TusXMLElement;
  208.   var aHandled: Boolean);
  209. const
  210.   NUM_ENTRIES = 2;
  211.   TagTable: array[0..NUM_ENTRIES - 1] of record
  212.     TagName: string;
  213.     ResolverClass: TTagResolverClass;
  214.   end = ((TagName:'CONTROL'; ResolverClass:TControlTagResolver),
  215.          (TagName:'DATAOBJECT'; ResolverClass:TDataObjectTagResolver)
  216.          );
  217. var
  218.   I: Integer;
  219.   S: string;
  220. begin
  221.   for I := 0 to NUM_ENTRIES - 1 do
  222.     with TagTable[I] do
  223.       if aElement.TagName = TagName then
  224.       begin
  225.         with ResolverClass.Create(Self, aElement) do
  226.           try
  227.             Setup;
  228.             Resolve;
  229.             S := GetHTML;
  230.             if S <> '' then
  231.               Self.HTML.Add(S);
  232.           finally
  233.             Free;
  234.           end;
  235.         aHandled := True;
  236.         Break;
  237.       end;
  238. end;
  239.  
  240. { TControlTagResolver }
  241.  
  242. procedure TControlTagResolver.GetAttributes;
  243. begin
  244.   inherited;
  245.   AType := GetAttribute('type', '');
  246.   AName := GetAttribute('name', '');
  247.   APropertyName := GetAttribute('property', '');
  248.   AValue := GetAttribute('value', '');
  249. end;
  250.  
  251. function TControlTagResolver.GetPropertyValue(aPropertyReference: string): string;
  252. var
  253.   ObjectName: string;
  254.   PropertyName: string;
  255.   I: Integer;
  256. begin
  257.   I := Pos('.', aPropertyName);
  258.   ObjectName := Copy(aPropertyName, 1, I - 1);
  259.   PropertyName := Copy(aPropertyName, I + 1, Length(aPropertyName) - I);
  260.   I := ObjectCache.IndexOf(ObjectName);
  261.   if I = -1 then
  262.     raise Exception.CreateFmt('Invalid object name: "%s"', [ObjectName]);
  263.   Result := TDataObject(ObjectCache.Objects[I]).PropertyByName(PropertyName).AsString;
  264. end;
  265.  
  266. procedure TControlTagResolver.Resolve;
  267. begin
  268.   if APropertyName <> '' then
  269.     AValue :=  GetPropertyValue(APropertyName);
  270.  
  271.   if AType = 'edit' then
  272.   begin
  273.     HTML.Add(Format('<INPUT type="text" name="%s" value="%s">',
  274.                     [AName, aValue]));
  275.   end;
  276. end;
  277.  
  278. { TSimpleControlTagResolver }
  279.  
  280. procedure TSimpleControlTagResolver.GetAttributes;
  281. begin
  282.   AType := GetAttribute('type', '');
  283.   if AType <> 'edit' then
  284.     raise Exception.CreateFmt('Illegal value for "type" attribute: %s', [AType]);
  285.   AName := GetAttribute('name', '');
  286.   AValue := GetAttribute('value', '');
  287. end;
  288.  
  289. procedure TSimpleControlTagResolver.Resolve;
  290. begin
  291.   if AType = 'edit' then
  292.   begin
  293.     HTML.Add(Format('<INPUT type="text" name="%s" value="%s">',
  294.                     [AName, aValue]));
  295.   end;
  296. end;
  297.  
  298. { TDataObjectTagResolver }
  299.  
  300. procedure TDataObjectTagResolver.GetAttributes;
  301. var
  302.   TempClass: TPersistentClass;
  303. begin
  304.   AClassName := GetAttribute('class', '');
  305.   AName := GetAttribute('name', '');
  306.   AOID := GetAttribute('oid', '');
  307.  
  308.   TempClass := GetClass(AClassName);
  309.   if not (Assigned(TempClass) or TempClass.InheritsFrom(TDataObject)) then
  310.     raise Exception.CreateFmt('%s is not a valid class', [AClassName]);
  311.   AClass := TDataObjectClass(TempClass);
  312. end;
  313.  
  314. procedure TDataObjectTagResolver.Resolve;
  315. var
  316.   Instance: TDataObject;
  317. begin
  318.   Instance := AClass.Create(MLEDatabase);
  319.   ObjectCache.AddObject(AName, Instance);
  320.   if AOID <> '' then
  321.     Instance.GetByOID(AOID);
  322. end;
  323.  
  324. initialization
  325.   ObjectCache := TObjectCache.Create;
  326. finalization
  327.   ObjectCache.Free;
  328. end.
  329.